package com.katze.boot.plugins.redis.operations;

import com.katze.boot.plugins.redis.RedisTemplateManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * 说  明：Redis 对Key-Value操作的封装
 * 作  者：zf.zeng
 * 日  期：2021-02-14 (星期日)
 **/
public class RedisValueOperations<V> {

    private final ValueOperations<String, V> valueOperations;
    private RedisTemplateManager<V> manager;

    public RedisValueOperations(RedisTemplate<String, V> redisTemplate){
        this.valueOperations = redisTemplate.opsForValue();
    }

    public RedisValueOperations(RedisTemplateManager<V> manager){
        this.manager = manager;
        this.valueOperations = manager.primary().opsForValue();
    }

    public <R>R select(int database, Function<ValueOperations<String, V>, R> function){
        return function.apply(database < 0? this.valueOperations:this.manager.select(database).opsForValue());
    }

    /**
     * 获取key对应的value
     * @param key 键
     */
    public V get(String key){
        return  this.valueOperations.get(key);
    }

    /**
     * 批量获取key对应的value
     * @param keys 键
     */
    public List<V> get(Collection<String> keys){
        return  this.valueOperations.multiGet(keys);
    }

    /**
     * 设定key对应的vlaue值
     * @param key 键
     * @param value 值
     */
    public void set(String key,V value){
        this.valueOperations.set(key, value);
    }


    /**
     * 设定key对应的vlaue值，并对value添加有效期(设置value的有效期)
     * @param key 键
     * @param value 值
     * @param time 有效时长（默认：秒）
     */
    public void set(String key, V value, long time){
        valueOperations.set(key, value, time, TimeUnit.SECONDS);
    }

    /**
     * 设定key对应的vlaue值，并对value添加有效期(设置value的有效期)
     * @param key 键
     * @param value 值
     * @param time 有效时长
     * @param unit 时间单位
     */
    public void set(String key, V value, long time, TimeUnit unit){
        valueOperations.set(key, value, time, unit);
    }


    /**
     * 如果key存在则覆盖value,反之则添加value
     * @param key 键
     * @param value 值
     * @return key存在返回旧value，则返回Null
     */
    public V getAndSet(String key,V value){
        return valueOperations.getAndSet(key, value);
    }


    /**
     * 批量设定key对应的vlaue值 (重复的键会覆盖)
     */
    public void multiSet(Map<String, V> keyAndValue){
        valueOperations.multiSet(keyAndValue);
    }

    /**
     * 批量设定key对应的vlaue值, 只有全部key不存在时才添加，反之则全部不添加
     */
    public void multiSetIfAbsent(Map<String, V> keyAndValue){
        valueOperations.multiSetIfAbsent(keyAndValue);
    }

    /**
     * key对应的vlaue进行加减操作,
     * 如果key不存在且value是长整型,则创建并赋值number
     * 如果key存在且value不是长整型,则报错
     * @param key 键
     * @param number 长整型数值
     * @return 新的value
     */
    public Long increment(String key,long number){
        return valueOperations.increment(key, number);
    }

    /**
     * key对应的vlaue进行加减操作,
     * 如果key不存在且value是双精度,则创建并赋值number
     * 如果key存在且value不是双精度,则报错
     * @param key 键
     * @param number 双精度数值
     * @return 新的value
     */
    public Double increment(String key,double number){
        return valueOperations.increment(key, number);
    }
}
